home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianPick.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
6KB
|
262 lines
/*ScianPick.c
Picking system for spaces in SciAn
Eric Pepke
May 30, 1991
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianLists.h"
#include "ScianWindows.h"
#include "ScianSpaces.h"
#include "ScianDraw.h"
#include "ScianIDs.h"
#include "ScianErrors.h"
#include "ScianPick.h"
#define MAXNPICKS 400 /*Maximum # of pick tuples*/
/*Product of the next two cannot be greater than 32767*/
#define MAXPICKEDOBJECTS 15 /*Maximum # of picked objects*/
#define MAXPICKEDVERTICES 2000 /*Maximum # of picked vertices*/
#ifdef GRAPHICS
static Matrix tempMatrix, pickMatrix;
#endif
short curPickObject; /*Current object being picked*/
long bestPickVertex;
short pickBuffer[MAXNPICKS * 2 + 1]; /*Pick buffer*/
struct POS
{
ObjPtr object;
long maxIndex;
Bool anyPicked;
};
struct POS pickObjects[MAXPICKEDOBJECTS]; /*Pickable objects*/
short hits[MAXNPICKS];
void StartPick()
/*Starts picking mode*/
{
#ifdef GRAPHICS
getmatrix(tempMatrix);
pick(pickBuffer, MAXNPICKS);
initnames();
loadname(-1);
curPickObject = -1;
MATCOPY(pickMatrix, Identity);
#endif
}
#ifdef PROTO
void PickObject(ObjPtr object, int resolveType)
#else
void PickObject(object, resolveType)
ObjPtr object;
int resolveType;
#endif
/*Declares that object is about to be drawn for picking*/
{
#ifdef GRAPHICS
++curPickObject;
if (curPickObject >= MAXPICKEDOBJECTS - 1)
{
ReportError("PickObject", "Too many objects to pick");
return;
}
pickObjects[curPickObject] . object = object;
pickObjects[curPickObject] . maxIndex = 0;
pickObjects[curPickObject] . anyPicked = false;
loadname(curPickObject * MAXPICKEDVERTICES);
#endif
}
#ifdef PROTO
void PickVertex(long vertex)
#else
void PickVertex(vertex)
long vertex;
#endif
/*Identifies a vertex number for picking*/
{
if (vertex > pickObjects[curPickObject] . maxIndex)
{
pickObjects[curPickObject] . maxIndex = vertex;
}
loadname(curPickObject * MAXPICKEDVERTICES +
vertex % MAXPICKEDVERTICES);
}
void EndPickObject(object)
ObjPtr object;
/*Ends the picking for object*/
{
#ifdef GRAPHICS
loadname(-1);
#endif
}
#ifdef PROTO
int CompareShorts(const void *a, const void *b)
#else
int CompareShorts(a, b)
void *a, *b;
#endif
/*Compares two shorts for qsort*/
{
return ((short *) a)[0] - ((short *) b)[0];
}
ObjPtr StopPick()
/*Stops picking mode and returns a list of objects*/
{
#ifdef GRAPHICS
int nHits, k, d, c;
ObjPtr retVal;
int whichObject;
long trimmedVertex;
long hitCounter;
int currentObject;
int tryVertex;
real px, py, pz;
FuncTyp method;
Matrix projMatrix, viewMatrix, curMatrix;
real xnew, ynew, znew, wnew;
real bestDist;
int bestVertex;
real r2;
bestPickVertex = -1;
/*Get the current matrix for transformation*/
mmode(MPROJECTION);
getmatrix(projMatrix);
mmode(MVIEWING);
getmatrix(viewMatrix);
MULTMATRIX(viewMatrix, projMatrix, curMatrix);
/*Restore the old matrix*/
loadmatrix(tempMatrix);
nHits = endpick(pickBuffer);
if (nHits < 0)
{
ReportError("StopPick", "Pick buffer was too small");
nHits = -nHits;
}
/*Go through the hits and distribute through the buffer*/
retVal = NULLOBJ;
if (nHits)
{
k = 0;
hitCounter = 0;
while (nHits)
{
c = pickBuffer[k];
++k;
while (c)
{
if (pickBuffer[k] >= 0)
{
hits[hitCounter++] = pickBuffer[k];
}
--c;
++k;
}
--nHits;
}
#if 0
whichObject = pickBuffer[k] / MAXPICKEDVERTICES;
trimmedVertex = pickBuffer[k] % MAXPICKEDVERTICES;
printf("%d ", trimmedVertex);
retVal = pickObjects[whichObject] . object;
#endif
/*Sort the hits*/
qsort(hits, hitCounter, sizeof(short), CompareShorts);
/*Uniq them*/
d = 0;
for (k = 1; k < hitCounter; ++k)
{
if (hits[k] != hits[d])
{
++d;
hits[d] = hits[k];
}
}
hitCounter = d + 1;
/*Go through the hits and see which one is the closest*/
bestDist = PLUSINF;
currentObject = -1;
for (k = 0; k < hitCounter; ++k)
{
whichObject = hits[k] / MAXPICKEDVERTICES;
trimmedVertex = hits[k] % MAXPICKEDVERTICES;
if (whichObject > currentObject)
{
currentObject = whichObject;
method = GetMethod(pickObjects[currentObject] . object,
BEGINSTUFFING);
if (method)
{
(*method)(pickObjects[currentObject] . object);
}
else
{
retVal = pickObjects[currentObject] . object;
}
method = GetMethod(pickObjects[currentObject] . object,
STUFFSELPOINT);
}
for (tryVertex = trimmedVertex;
tryVertex <= pickObjects[currentObject] . maxIndex;
tryVertex += MAXPICKEDVERTICES)
{
if (method)
{
(*method)(pickObjects[currentObject] . object,
tryVertex, &px, &py, &pz);
xnew = px * curMatrix[0][0] + py * curMatrix[1][0] +
pz * curMatrix[2][0] + curMatrix[3][0];
ynew = px * curMatrix[0][1] + py * curMatrix[1][1] +
pz * curMatrix[2][1] + curMatrix[3][1];
znew = px * curMatrix[0][2] + py * curMatrix[1][2] +
pz * curMatrix[2][2] + curMatrix[3][2];
wnew = px * curMatrix[0][3] + py * curMatrix[1][3] +
pz * curMatrix[2][3] + curMatrix[3][3];
xnew /= wnew;
ynew /= wnew;
znew /= wnew;
r2 = xnew * xnew + ynew * ynew;
if (r2 < bestDist)
{
retVal = pickObjects[currentObject] . object;
bestPickVertex = tryVertex;
bestDist = r2;
}
}
}
}
}
return retVal;
#endif
}